﻿using System;
using System.Collections.Specialized;
using JetBrains.Annotations;
using System.Linq;

namespace StreetPacMan.FrontEnd.Infra
{
    public interface IServerPollParametersConverter
    {
        //ServerPollParameters GetServerPollParametersFromRequest(NameValueCollection nameValueCollection);
        //GetGameStateParameters GetGameStateParametersFromRequest(NameValueCollection nameValueCollection);
        //CreateGameParameters GetCreateGameParametersFromRequest(NameValueCollection nameValueCollection);
        //JoinGameParameters GetJoinGameParametersFromRequest(NameValueCollection nameValueCollection);
        //SendGameMessageParameters GetSendGameMessageParametersFromRequest(NameValueCollection nameValueCollection);
        //REMOVEME_CopyApplesFromOneGameToAnotherParameters GetREMOVEME_CopyApplesFromOneGameToAnotherParametersFromRequest(NameValueCollection nameValueCollection);
        object GetFor(Type objectType, NameValueCollection nvc);
    }

    internal static class NameValueCollectionExtensions
    {
        public static string AsPascalCase(this string source)
        {
            return char.IsUpper(source[0]) ? source : char.ToUpper(source[0]) + source.Substring(1);
        }

        //public static T GetX<T>(this NameValueCollection source, string keyName)
        //{
        //    var stringValue = source[keyName];
        //    if(stringValue==null)
        //    {
        //        throw new ArgumentException(string.Format("Missing {0} arguemnt", keyName));
        //    }
        //    if(typeof(T) == typeof(int))
        //    {
        //        int result;
        //        if (int.TryParse(stringValue, out result) == false)
        //        {
        //            throw new ArgumentException(string.Format("The value of {0} is not a legal int ({1})", keyName, stringValue));
        //        }
        //        return result;
        //    }
        //    if (typeof(T) == typeof(double))
        //    {
        //        double result;
        //        if (double.TryParse(stringValue, out result) == false)
        //        {
        //            throw new ArgumentException(string.Format("The value of {0} is not a legal double ({1})", keyName, stringValue));
        //        }
        //        return result;
        //    }
        //    if (typeof(T) == typeof(bool))
        //    {
        //        bool result;
        //        if (bool.TryParse(stringValue, out result) == false)
        //        {
        //            throw new ArgumentException(string.Format("The value of {0} is not a legal bool ({1})", keyName, stringValue));
        //        }
        //        return result;
        //    }
        //    if (typeof(T) == typeof(string))
        //    {
        //        return stringValue;
        //    }
        //    throw new ApplicationException();
        //}
    }

    [UsedByIoc]
    public class ServerPollParametersConverter : IServerPollParametersConverter
    {
        public object GetFor(Type objectType, NameValueCollection nvc)
        {
            var ctorWithMostArguemnts = objectType.GetType()
                .GetConstructors()
                .OrderByDescending(x => x.GetParameters().Length)
                .First();

            var args = ctorWithMostArguemnts
                .GetParameters()
                .Select(x => GetArg(nvc,x.ParameterType, x.Name.AsPascalCase()))
                .ToArray();

            return ctorWithMostArguemnts.Invoke(args);
        }

        private object GetArg(NameValueCollection source, Type parameterType, string argName)
        {
            var stringValue = source[argName];
            if (stringValue == null)
            {
                throw new ArgumentException(string.Format("Missing {0} arguemnt", argName));
            }
            if (parameterType == typeof(int))
            {
                int result;
                if (int.TryParse(stringValue, out result) == false)
                {
                    throw new ArgumentException(string.Format("The value of {0} is not a legal int ({1})", argName, stringValue));
                }
                return result;
            }
            if (parameterType.IsEnum)
            {
                int result;
                if (int.TryParse(stringValue, out result) == false)
                {
                    throw new ArgumentException(string.Format("The value of {0} is not a legal int ({1})", argName, stringValue));
                }
                return Enum.ToObject(parameterType, result);
            }
            if (parameterType == typeof(double))
            {
                double result;
                if (double.TryParse(stringValue, out result) == false)
                {
                    throw new ArgumentException(string.Format("The value of {0} is not a legal double ({1})", argName, stringValue));
                }
                return result;
            }
            if (parameterType == typeof(bool))
            {
                bool result;
                if (bool.TryParse(stringValue, out result) == false)
                {
                    throw new ArgumentException(string.Format("The value of {0} is not a legal bool ({1})", argName, stringValue));
                }
                return result;
            }
            if (parameterType == typeof(string))
            {
                return stringValue;
            }
            throw new ApplicationException();
        }
        //public void Test()
        //{
        //    GetServerPollParametersFromRequest(new NameValueCollection
        //                                           {
        //                                               { "EntityId", "4" },
        //                                               { "GeoLat", "4" },
        //                                               { "GeoLng", "4" },
        //                                               { "IsEnabled", "true" },
        //                                               { "UpdateMeForTheLastXSeconds", "4" },
        //                                           });
        //}
        //public ServerPollParameters GetServerPollParametersFromRequest(NameValueCollection nvc)
        //{
        //    return new ServerPollParameters(
        //        nvc.GetX<int>("EntityId"),
        //        nvc.GetX<double>("GeoLat"),
        //         nvc.GetX<double>("GeoLng"),
        //         nvc.GetX<bool>("IsEnabled"),
        //         nvc.GetX<int>("UpdateMeForTheLastXSeconds"));
        //}

        //public GetGameStateParameters GetGameStateParametersFromRequest(NameValueCollection nvc)
        //{
        //    return new GetGameStateParameters(nvc.GetX<int>("EntityId"));
        //}

        //public CreateGameParameters GetCreateGameParametersFromRequest(NameValueCollection nvc)
        //{
        //    return new CreateGameParameters(nvc.GetX<string>("Name"));
        //}

        //public JoinGameParameters GetJoinGameParametersFromRequest(NameValueCollection nvc)
        //{
        //    return new JoinGameParameters(nvc.GetX<string>("GameName"), nvc.GetX<string>("PlayerName"), (PlayerRole)nvc.GetX<int>("Role"));
        //}

        //public SendGameMessageParameters GetSendGameMessageParametersFromRequest(NameValueCollection nvc)
        //{
        //    return new SendGameMessageParameters(nvc.GetX<int>("SenderId"), nvc.GetX<string>("MessageText"));
        //}

        //public REMOVEME_CopyApplesFromOneGameToAnotherParameters GetREMOVEME_CopyApplesFromOneGameToAnotherParametersFromRequest(NameValueCollection nvc)
        //{
        //    return new REMOVEME_CopyApplesFromOneGameToAnotherParameters(nvc.GetX<int>("OriginGameId"), nvc.GetX<int>("DestinationGameId"));
        //}
    }
}